package charles.testproject.xmlparser;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import java.util.Iterator;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import charles.testproject.googleapi.GoogleMapHttp;

import sun.net.www.URLConnection;

public class GoogleCalendarXMLParser {
	private static final Logger logger = Logger.getLogger(GoogleMapHttp.class);
	private static final String ENTRY_ELEMENT = "entry";
	private static final String TITLE_ELEMENT = "title";
	private static final String SUMMURY_ELEMENT = "summary";
	private static final String CONTENT_ELEMENT = "content";
	
	public Vector<String> getCalendarScheduleDoingNow(String googleAccount){
		//a Vector container of string arrays that filled with schedule's date and content  
		Vector<String> googleShedule = new Vector<String>(2,1);
			
		String url = "http://www.google.com/calendar/feeds/" + googleAccount + "/public/basic";
		
		try {
			//get a <Date> today
			Date date = new Date();
		    SimpleDateFormat df = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss");
		    String SystemDateNTime = df.format(date).toString();
		    String[] dateNTimeSplitArr = SystemDateNTime.split(" ");
		    //remove the blank character we don't need
		    for(String strItem : dateNTimeSplitArr) {
		    	strItem = strItem.replaceAll(" ", "");
		    }
		    //these characteristic and int values are use for judging the schedule event , 
		    //see if the events are now doing
		    String thisYear = dateNTimeSplitArr[3];
		    String thisMonthNDay = dateNTimeSplitArr[2] + " " + dateNTimeSplitArr[1];
		    String thisTime = dateNTimeSplitArr[dateNTimeSplitArr.length - 1];
		    String[] thisTimeSplitArr = thisTime.split(":");
		    int thisTimeInt = Integer.parseInt(thisTimeSplitArr[0]) * 100 + Integer.parseInt(thisTimeSplitArr[1]);
			
		    //fetch this <code>googleAccount<code>'s google schedule by using the public URL
			URL calendarURL = new URL(url);
			HttpURLConnection calendarConnection = null;
			calendarConnection = (HttpURLConnection)calendarURL.openConnection();
			//make sure very time we get the schedule xml file's language is english, because we can not
			//handle other language so far
			calendarConnection.setRequestProperty("Accept-Language", "en-us,zh-cn;q=0.7,en;q=0.3");
			InputStream is = calendarConnection.getInputStream();
			int read = is.read();
			while(read != -1) {
				System.out.print((char)read);
				read =is.read();
			}
			
			//build a document by using the xml input stream got from calender.google.com
			DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder  docBuilder = docFactory.newDocumentBuilder();
			Document doc = docBuilder.parse(is);
			
			//start to parser the XML
			NodeList entryNodeList = doc.getElementsByTagName(ENTRY_ELEMENT);
			for(int i = 0; i < entryNodeList.getLength(); i++){
				
				Node entryNode = entryNodeList.item(i);
				Element entryElement = (Element)entryNode;
				
				String dateNtimeStr = "";
				String scheduleEventStr = "";
				String timeNScheduleEventStr = null;
				
				//in google calendar xml feed file , the Date N' Time info are contain by <summary> node
				NodeList dateNtimeList = entryElement.getElementsByTagName(SUMMURY_ELEMENT);
				if(dateNtimeList.getLength() == 0) {
					//if there have no <summary> node try <content> node instead
					dateNtimeList = entryElement.getElementsByTagName(CONTENT_ELEMENT);
				}
				for(int j = 0; j < dateNtimeList.getLength(); j++){
				    //get Date N' Time value
					dateNtimeStr = dateNtimeList.item(j).getFirstChild().getNodeValue();
				}
				
				//in google calendar xml feed file , the schedule event's info are contain by <title> node
				NodeList scheduleEventList = entryElement.getElementsByTagName(TITLE_ELEMENT);
				for(int j = 0; j < scheduleEventList.getLength(); j++){
					//get schedule event's value
					scheduleEventStr = scheduleEventList.item(j).getFirstChild().getNodeValue();
				}
				
				//judge and format the <code>dateNtimeStr<\code>,first make sure it's today's schedule
				if(dateNtimeStr.contains(thisYear) 
						&& dateNtimeStr.contains(thisMonthNDay)) {
					//contain the two time point of one schedule event
					ArrayList<String> timeBetween = new ArrayList<String>(2);
                    //regular expression match the time form like "7am" , "7pm","7:30am","7:30pm"
					String regex = "([^0-9])([0-1]?[0-9]){1}((|(:([0-5]){1}([0-9]){1}){1,2})(([AP]M)|([ap]m)))";
					Pattern p = Pattern.compile(regex);
					Matcher m = p.matcher(dateNtimeStr);
					
					
					while(m.find()){
						System.out.println(m.group(0));
						timeBetween.add(transformTime(m.group(0)));
					}
					
					//must handle the special case in 12 midnight ,It's form will be like "12am" "12:30am"
					if(timeBetween.size() == 2) {
						String fixTime = "";
						if(Integer.parseInt(timeBetween.get(0)) > Integer.parseInt(timeBetween.get(1))){
							if(Integer.parseInt(timeBetween.get(0)) == 1200 | 
									Integer.parseInt(timeBetween.get(0)) == 1230) {
								//if the 12 midnight time point is a begin time point , minus 1200
								fixTime = (Integer.parseInt(timeBetween.get(0)) - 1200) + "";
								timeBetween.set(0,fixTime);
							}
							else if(Integer.parseInt(timeBetween.get(1)) == 1200) {
								//if the 12 midnight time point is end time point , plus 1200
								fixTime = (Integer.parseInt(timeBetween.get(1)) + 1200) + "";
								timeBetween.set(1,fixTime);
							}
								
						} 
					} else {
						logger.error("the number of time point in the timeBetween <t>ArrayList<\t> is wrong...");
					}
					
					int EventStartTime = Integer.parseInt(timeBetween.get(0));
					int EventEndTime   = Integer.parseInt(timeBetween.get(1));
					//secondly make sure the event is processing now 
					if(thisTimeInt >= EventStartTime && thisTimeInt <= EventEndTime ) {
						//the final google schedule will be like "1200-1400 doing something"
						timeNScheduleEventStr = timeBetween.get(0) + "-" + timeBetween.get(1) + " " + scheduleEventStr;
						//adding the schedule into it's container
						googleShedule.add(timeNScheduleEventStr);
					}
					
				}
			}
			
			Iterator<String> scheduleIter = googleShedule.iterator();
			while(scheduleIter.hasNext()){
				System.out.println("googele schedule event : " + scheduleIter.next());
			}
			
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			System.out.println("Exceptin accured, can not get scheduel for " + googleAccount + " please check the account");
			e.printStackTrace();

		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		}
		
		if(googleShedule.isEmpty()) {
			googleShedule.add("No schedule for now");
		}
		
		return googleShedule;
	}
	/**
	 * "7am" , "7pm","7:30am","7:30pm" ---> military time "700" ,"1900","730","1930"
	 * @param form12Time a date characteristic like this "1pm" "1:30am"
	 * @return
	 */
	private String transformTime(String form12Time) {
		int militaryTime = 0;
		String firstNum = null;
		//remove the blank character that we don't need
		if(form12Time.contains(" ")) {
			form12Time = form12Time.replaceAll(" ", "");
		}
		
		if(form12Time.contains("am")) {
			
			if(form12Time.contains(":")){
				firstNum = form12Time.substring(0, form12Time.indexOf(":"));
				if(firstNum != null) {
					militaryTime  = Integer.parseInt(firstNum)*100 + 30;
				}
			} 
			else {
				firstNum = form12Time.substring(0, form12Time.indexOf("a"));
				if(firstNum != null) {
					militaryTime  = Integer.parseInt(firstNum)*100;
				}
			}
			
		} 
		else if(form12Time.contains("pm")){
			
			if(form12Time.contains(":")){
				firstNum = form12Time.substring(0, form12Time.indexOf(":"));
				if(firstNum != null) {
					//must handle the special case the 12 noon ,It's form will be like "12pm" "12:30pm"
					if(Integer.parseInt(firstNum) == 12) {
						militaryTime = Integer.parseInt(firstNum)*100 + 30;
					} 
					else {
						militaryTime  = Integer.parseInt(firstNum)*100 + 1200 + 30;
					}
				}
			} 
			else {
				firstNum = form12Time.substring(0, form12Time.indexOf("p"));
				if(firstNum != null) {
					//must handle the special case the 12 noon ,It's form will be like "12pm" "12:30pm"
					if(Integer.parseInt(firstNum) == 12) {
						militaryTime = Integer.parseInt(firstNum)*100;
					} 
					else {
						militaryTime  = Integer.parseInt(firstNum)*100 + 1200;
					}
				}
			}
			
		} 
		else {
			logger.error("the dateNtimeStr's form was wrong...");
		}
		
		return new String(militaryTime + "");
	}

	public static void main(String[] args) {
		GoogleCalendarXMLParser googleMapHttp = new GoogleCalendarXMLParser();
		googleMapHttp.getCalendarScheduleDoingNow("sancho.lai@gmail.com");
	    //wrong account for testing
//		googleMapHttp.getCalendarScheduleDoingNow("charles_lai@foxmail.com");
	}

}
